/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxline.clinicplus.manager;

import br.com.foxline.clinicplus.entity.*;
import br.com.foxline.clinicplus.enums.TypeIncome;
import br.com.foxline.clinicplus.service.CashService;
import br.com.foxline.clinicplus.service.ContaBancariaServico;
import br.com.foxline.clinicplus.service.IncomeService;
import br.com.foxline.clinicplus.service.OperatorService;
import br.com.foxline.clinicplus.vo.VoContaValor;
import br.com.foxline.clinicplus.vo.VoResumoCaixa;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.model.DualListModel;

/**
 *
 * @author roniere
 */
@ManagedBean
@ViewScoped
public class ManagerIncome implements Serializable {

    @EJB
    IncomeService incomeService;
    @EJB
    OperatorService operatorService;
    @EJB
    CashService cashService;
    @EJB
    ContaBancariaServico contaBancariaServico;
    private Procedure procedure;
    private SystemUser systemUser;
    private Doctor doctor;
    private Date date;
    private List<Income> incomes;
    private List<Income> incomesReceitas;
    private List<Income> incomesOutput;
    private BigDecimal total;
    private BigDecimal totalReceitas;
    /**
     * Somador de despesas por caixa de fluxo
     */
    private BigDecimal totalOutput;
    /**
     * Somador de todas as depesas
     */
    private BigDecimal totalOutputAll;
    private Date dateInitial;
    private Date dateFinal;
    private DualListModel<Operator> listOperators;
    private List<Income> incomesAll;

    @PostConstruct
    public void init() {
        listOperators = new DualListModel<Operator>(operatorService.findAll(), new ArrayList<Operator>());
        initial();
        dateInitial = new Date();
        dateFinal = new Date();
    }

    public void initial() {
        Calendar gc = GregorianCalendar.getInstance();
        if (dateInitial != null) {
            gc.setTime(dateInitial);
        }
        gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
        gc.set(GregorianCalendar.MINUTE, 0);
        gc.set(GregorianCalendar.SECOND, 0);
        gc.set(GregorianCalendar.MILLISECOND, 0);

        Calendar gc1 = GregorianCalendar.getInstance();
        if (dateInitial != null) {
            gc1.setTime(dateInitial);
            gc1.set(GregorianCalendar.HOUR_OF_DAY, 23);
            gc1.set(GregorianCalendar.MINUTE, 59);
            gc1.set(GregorianCalendar.SECOND, 59);
            gc1.set(GregorianCalendar.MILLISECOND, 59);
        } else {
            gc1.add(GregorianCalendar.DAY_OF_MONTH, 1);
            gc1.set(GregorianCalendar.HOUR_OF_DAY, 0);
            gc1.set(GregorianCalendar.MINUTE, 0);
            gc1.set(GregorianCalendar.SECOND, 0);
            gc1.set(GregorianCalendar.MILLISECOND, 0);
        }

        if (listOperators.getTarget() == null || listOperators.getTarget().isEmpty()) {
            total = incomeService.getValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.C, null, null, null, null, null, null, null, null, true);
            incomes = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.C, null, null, null, null, null, null, null, null, true);
            incomesAll = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, systemUser, null, null, null, null, null, null, null, null, null, null);
        } else {
            total = incomeService.getValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.C, null, null, null, listOperators.getTarget(), null, null, null, null, null);
            incomes = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.C, null, null, null, listOperators.getTarget(), null, null, null, null, null);
            incomesAll = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, systemUser, null, null, null, null, listOperators.getTarget(), null, null, null, null, null);
        }

        totalReceitas = incomeService.getValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.R, null, null, null, null, null, null, null, null, null);
        incomesReceitas = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.R, null, null, null, null, null, null, null, null, null);

        totalOutputAll = incomeService.getValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.D, null, null, null, null, null, null, null, null, null);

        if (totalOutputAll != null && totalOutputAll.compareTo(BigDecimal.ZERO) >= 0) {
            totalOutputAll = totalOutputAll.multiply(new BigDecimal("-1"));
        }


//        totalOutput = BigDecimal.ZERO;
//        Cash c = new Cash();
//        c.setTypeIncome(TypeIncome.D);
//        for (ContaBancaria cb : contaBancariaServico.getContaCaixaFluxo()) {
//            totalOutput = totalOutput.add(cashService.searchValueCash(gc.getTime(), gc1.getTime(), cb, c));
//        }

        incomesOutput = incomeService.findIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.D, null, null, null, null, null, null, null, null, null);

        /*
         * Soma todas as saidas que são de contas de fluxo de caixa COFRE
         */
        totalOutput = BigDecimal.ZERO;
        Cash c = new Cash();
        c.setTypeIncome(TypeIncome.D);
        for (Income income : incomesOutput) {
            if (income.getCash() != null && income.getCash().getContaBancaria() != null) {
                for (ContaBancaria cb : contaBancariaServico.getContaCaixaFluxo()) {
                    if (cb.getId() == income.getCash().getContaBancaria().getId()) {
                        totalOutput = totalOutput.add(cashService.find(income.getCash().getId()).getValue());
                        break;
                    }
                }
            }
        }

    }

    private void getInitialValue() {
        Calendar gc = GregorianCalendar.getInstance();
        gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
        gc.set(GregorianCalendar.MINUTE, 0);
        gc.set(GregorianCalendar.SECOND, 0);
        gc.set(GregorianCalendar.MILLISECOND, 0);

        Calendar gc1 = GregorianCalendar.getInstance();
        gc1.add(GregorianCalendar.DAY_OF_MONTH, 1);
        gc1.set(GregorianCalendar.HOUR_OF_DAY, 0);
        gc1.set(GregorianCalendar.MINUTE, 0);
        gc1.set(GregorianCalendar.SECOND, 0);
        gc1.set(GregorianCalendar.MILLISECOND, 1);
        incomeService.findValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null);
    }

    public DualListModel<Operator> getListOperators() {
        return listOperators;
    }

    public void setListOperators(DualListModel<Operator> listOperators) {
        this.listOperators = listOperators;
    }

    public BigDecimal getTotal() {
        return total;
    }

    public void setTotal(BigDecimal total) {
        this.total = total;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Doctor getDoctor() {
        return doctor;
    }

    public void setDoctor(Doctor doctor) {
        this.doctor = doctor;
    }

    public IncomeService getIncomeService() {
        return incomeService;
    }

    public void setIncomeService(IncomeService incomeService) {
        this.incomeService = incomeService;
    }

    public List<Income> getIncomes() {
        return incomes;
    }

    public void setIncomes(List<Income> incomes) {
        this.incomes = incomes;
    }

    public Procedure getProcedure() {
        return procedure;
    }

    public void setProcedure(Procedure procedure) {
        this.procedure = procedure;
    }

    public SystemUser getSystemUser() {
        return systemUser;
    }

    public void setSystemUser(SystemUser systemUser) {
        this.systemUser = systemUser;
    }

    public List<Income> getIncomesOutput() {
        return incomesOutput;
    }

    public void setIncomesOutput(List<Income> incomesOutput) {
        this.incomesOutput = incomesOutput;
    }

    public BigDecimal getTotalOutput() {
        return totalOutput;
    }

    public void setTotalOutput(BigDecimal totalOutput) {
        this.totalOutput = totalOutput;
    }

    public void searchByDate() {

        if (listOperators.getTarget() == null || listOperators.getTarget().isEmpty()) {
            total = incomeService.getValueIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.C, null, null, null, null, null, null, null, null, null);
            incomes = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.C, null, null, null, null, null, null, null, null, null);
            incomesAll = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, null, null, null, null, null, null, null, null, null, null);
            
        } else {
            total = incomeService.getValueIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.C, null, null, null, listOperators.getTarget(), null, null, null, null, null);
            incomes = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.C, null, null, null, listOperators.getTarget(), null, null, null, null, null);
            incomesAll = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, null, null, null, null, listOperators.getTarget(), null, null, null, null, null);
        }
        totalReceitas = incomeService.getValueIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.R, null, null, null, null, null, null, null, null, null);
        incomesReceitas = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.R, null, null, null, null, null, null, null, null, null);


        totalOutputAll = incomeService.getValueIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.D, null, null, null, null, null, null, null, null, null);
        totalOutput = BigDecimal.ZERO;
        Cash c = new Cash();
        c.setTypeIncome(TypeIncome.D);
        for (ContaBancaria cb : contaBancariaServico.getContaCaixaFluxo()) {
            totalOutput = totalOutput.add(cashService.searchValueCash(dateInitial, dateFinal, cb, c));
        }
        incomesOutput = incomeService.findIncomeGeneric(null, null, null, dateInitial, dateFinal, null, null, TypeIncome.D, null, null, null, null, null, null, null, null, null);

        if (totalOutputAll != null && totalOutputAll.compareTo(BigDecimal.ZERO) == 1) {
            totalOutputAll = totalOutputAll.multiply(new BigDecimal("-1"));
        }
    }

    public Date getDateFinal() {
        return dateFinal;
    }

    public void setDateFinal(Date dateFinal) {
        this.dateFinal = dateFinal;
    }

    public Date getDateInitial() {
        return dateInitial;
    }

    public void setDateInitial(Date dateInitial) {
        this.dateInitial = dateInitial;
    }

    public void report() {
        incomeService.reportIncomeAll(incomes, "Relatório");
    }

    public void reportGeral() {
        BigDecimal saldoAnterior = BigDecimal.ZERO;
        for (ContaBancaria contaBancaria : contaBancariaServico.autocomplete("")) {
            if(contaBancaria.isContaFluxo()){
                saldoAnterior = saldoAnterior.add(cashService.saldoAnterior(contaBancaria, dateInitial));
            }
        }
        incomeService.reportIncomeGeral(incomes, incomesReceitas, incomesOutput, total, totalReceitas, totalOutput, saldoAnterior);
    }

    public void resumoCaixa() {
        VoResumoCaixa resumoCaixa = new VoResumoCaixa();
        List<VoContaValor> contasSaldos = new ArrayList<VoContaValor>();
        List<VoContaValor> contasDespesas = new ArrayList<VoContaValor>();
        Cash c = new Cash();
        c.setTypeIncome(TypeIncome.D);

        for (ContaBancaria contaBancaria : contaBancariaServico.autocomplete("")) {
            contasSaldos.add(new VoContaValor(contaBancaria.getBanco().getNome() + " " + contaBancaria.getAgencia(),
                    cashService.sumCash(contaBancaria, dateInitial)));
        }
        resumoCaixa.setContasSaldos(contasSaldos);
        for (ContaBancaria contaBancaria : contaBancariaServico.autocomplete("")) {
            contasDespesas.add(new VoContaValor(contaBancaria.getBanco().getNome() + " " + contaBancaria.getAgencia(),
                    despesasPorCaixa(contaBancaria, dateInitial)));
        }
        resumoCaixa.setContasDespesas(contasDespesas);
        if (total == null) {
            total = BigDecimal.ZERO;
        }
        if (total != null) {
            BigDecimal totalresumo = BigDecimal.ZERO;
            totalresumo = totalresumo.add(total);

            if (totalReceitas != null) {
                resumoCaixa.setReceitas(total.add(totalReceitas));
                totalresumo = totalresumo.add(totalReceitas);
            } else {
                resumoCaixa.setReceitas(total);
            }

            if (totalOutput != null) {
                totalresumo = totalresumo.add(totalOutput);
            }
            resumoCaixa.setTotal(totalresumo);
        }
        resumoCaixa.setDespesas(totalOutput);


        incomeService.reportResumoCaixa(resumoCaixa, dateInitial);
    }

    public BigDecimal despesasPorCaixa(ContaBancaria contaBancaria, Date data) {
        if (data != null) {
            dateInitial = data;
            dateFinal = data;
        } else {
            dateInitial = new Date();
            dateFinal = new Date();
        }
        Cash c = new Cash();
        c.setTypeIncome(TypeIncome.D);
        return cashService.searchValueCashComIncome(dateInitial, dateFinal, contaBancaria, c);
    }

    public List<Income> getIncomesReceitas() {
        return incomesReceitas;
    }

    public void setIncomesReceitas(List<Income> incomesReceitas) {
        this.incomesReceitas = incomesReceitas;
    }

    public BigDecimal getTotalReceitas() {
        return totalReceitas;
    }

    public void setTotalReceitas(BigDecimal totalReceitas) {
        this.totalReceitas = totalReceitas;
    }

    public BigDecimal getTotalOutputAll() {
        return totalOutputAll;
    }

    public void setTotalOutputAll(BigDecimal totalOutputAll) {
        this.totalOutputAll = totalOutputAll;
    }

    public BigDecimal valorPorConvenio(Operator op, Date d) {
        if (d == null) {
            d = new Date();
        }
        Calendar gc = GregorianCalendar.getInstance();
        gc.setTime(d);

        gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
        gc.set(GregorianCalendar.MINUTE, 0);
        gc.set(GregorianCalendar.SECOND, 0);
        gc.set(GregorianCalendar.MILLISECOND, 0);

        Calendar gc1 = GregorianCalendar.getInstance();
        gc1.setTime(d);

        gc1.set(GregorianCalendar.HOUR_OF_DAY, 23);
        gc1.set(GregorianCalendar.MINUTE, 59);
        gc1.set(GregorianCalendar.SECOND, 59);
        gc1.set(GregorianCalendar.MILLISECOND, 59);
        return incomeService.getValueIncomeGeneric(null, null, null, gc.getTime(), gc1.getTime(), null, null, TypeIncome.C,
                null, null, op, null, null, null, null, null, true);
    }
    
    
    public void reportUser() {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
        String titulo = "CAIXA";
        if(systemUser != null){
            titulo += " - " + (systemUser != null ? systemUser.getName() : "") + " - ";
        }
        if(dateInitial != null && dateFinal != null){
            titulo += " "+(dateInitial != null ? sdf.format(dateInitial) + " até " : "") + ""
                + (dateFinal != null ? sdf.format(dateFinal) : "");
        }
        
        if(totalOutput != null && totalOutput.compareTo(BigDecimal.ZERO) >= 0){
            totalOutput = totalOutput.multiply(new BigDecimal("-1"));
        }
        incomeService.reportCaixaResumo(incomesAll, titulo, total, totalOutput);
    }
    
}
